package edu.haw.cg.datastructures;

/**
 * 
 * Praktikum CG WP WS13/14
 * Gruppe: Andreas Rebri(andreas.rebri@haw-hamburg.de)
 * 		   Joschka Schulz(joschka.schulz@haw-hamburg.de)
 * Aufgabe : Aufgabenblatt 4
 * Verwendete Quellen: -
 */

import java.util.ArrayList;
import java.util.List;

import javax.vecmath.Point3f;

/**
 *  Utility-Class for converting triangle mesh to HalfEdgeDatastructure
 */
public class MeshToHalfEdgeConverter {
	
	/**
	 * Converts given TriangleMesh to HalfEdgeDatastructure
	 * 
	 * @param mesh the given TriangleMesh
	 * @return a converted HalfEdgeDatastructure
	 */
	public static HalfEdgeDatastructure converterMeshToHalfEdge(
			TriangleMesh mesh) {
		
		//An empty halfEdgeMesh for the conversion
		HalfEdgeDatastructure halfEdgeMesh = new HalfEdgeDatastructure();
		
		//Temporary HalfEdgeTriangle variable
		IHalfEdgeFacet halfEdgleTriangle;
		
		//A list of all vertices in the halfEdgeMesh for counting indices
		List<HalfEdgeVertex> vertices = new ArrayList<>();
		
		//All edges without opposites
		List<HalfEdge> edgesWithoutOpposites = new ArrayList<>();
		
		//A temporary Triangle variable
		Triangle triangle;
		
		//Indices for the three vertices of a triangle
		int vIndex1, vIndex2, vIndex3;
		
		//Temporary HalfEdge variables
		HalfEdge e1, e2, e3;
		
		//Iterates over all Triangles of the given mesh
		for (int i = 0, n = mesh.getNumberOfTriangles(); i < n; i++) {
			triangle = mesh.getTriangle(i);

			//Add vertex to halfEdgeMesh if the vertex isn't already in it
			HalfEdgeVertex v1 = new HalfEdgeVertex(new Point3f(
					mesh.getVertex(triangle.getVertex1())));
			if (!vertices.contains(v1)) {
				vIndex1 = halfEdgeMesh.addVertex(v1);
				vertices.add(v1);
			} else {
				vIndex1 = vertices.indexOf(v1);
			}

			HalfEdgeVertex v2 = new HalfEdgeVertex(new Point3f(
					mesh.getVertex(triangle.getVertex2())));
			if (!vertices.contains(v2)) {
				vIndex2 = halfEdgeMesh.addVertex(v2);
				vertices.add(v2);
			} else {
				vIndex2 = vertices.indexOf(v2);
			}

			HalfEdgeVertex v3 = new HalfEdgeVertex(new Point3f(
					mesh.getVertex(triangle.getVertex3())));
			if (!vertices.contains(v3)) {
				vIndex3 = halfEdgeMesh.addVertex(v3);
				vertices.add(v3);
			} else {
				vIndex3 = vertices.indexOf(v3);
			}

			//Creates a new HalfEdge for every edge of the triangle
			e1 = new HalfEdge();
			halfEdgeMesh.addHalfEdge(e1);
			e2 = new HalfEdge();
			halfEdgeMesh.addHalfEdge(e2);
			e3 = new HalfEdge();
			halfEdgeMesh.addHalfEdge(e3);

			halfEdgleTriangle = new HalfEdgeTriangle();

			//Adding to every vertex the edge and to every edge the vertex
			v1 = halfEdgeMesh.getVertex(vIndex1);
			e1.setVertex(v1);
			v1.setHalfEdge(e1);
			
			v2 = halfEdgeMesh.getVertex(vIndex2);
			e2.setVertex(v2);
			v2.setHalfEdge(e2);
			
			v3 = halfEdgeMesh.getVertex(vIndex3);
			e3.setVertex(v3);
			v2.setHalfEdge(e3);

			
			//Sets the next, previous and name of the edges
			e1.setNext(e2);
			e1.setPrev(e3);
			e1.setName(i + "e1");

			e2.setNext(e3);
			e2.setPrev(e1);
			e2.setName(i + "e2");

			e3.setNext(e1);
			e3.setPrev(e2);
			e3.setName(i + "e3");
			halfEdgleTriangle.setHalfEdge(e1);
			
			//Added the three new edges to the edges without Opposites
			edgesWithoutOpposites.add(e1);
			edgesWithoutOpposites.add(e2);
			edgesWithoutOpposites.add(e3);

			//Checks which edges got an opposite
			for (HalfEdge e : edgesWithoutOpposites) {
				if (e.getNext().getVertex().getPosition()
						.equals(e1.getVertex().getPosition())) {
					e.setOpposite(e1);
					e1.setOpposite(e);
				} else if (e.getNext().getVertex().getPosition()
						.equals(e2.getVertex().getPosition())) {
					e.setOpposite(e2);
					e2.setOpposite(e);
				} else if (e.getNext().getVertex().getPosition()
						.equals(e3.getVertex().getPosition())) {
					e.setOpposite(e3);
					e3.setOpposite(e);
				}
			}

			//Adding the facets
			halfEdgeMesh.addFacet(halfEdgleTriangle);
			e1.setFacet(halfEdgleTriangle);
			e2.setFacet(halfEdgleTriangle);
			e3.setFacet(halfEdgleTriangle);

		}

		return halfEdgeMesh;
	}
}
